home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 201-225 / disk_217 / stevie / misccmds.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  9KB  |  430 lines

  1. /*
  2.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  3.  *
  4.  * Code Contributions By : Tim Thompson           twitch!tjt
  5.  *                         Tony Andrews           onecom!wldrdg!tony 
  6.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  7.  */
  8.  
  9. #include "stevie.h"
  10.  
  11. extern int      did_ai;
  12.  
  13. /*
  14.  * OpenForward 
  15.  *
  16.  * Add a blank line below the current line. 
  17.  */
  18.  
  19. bool_t
  20. OpenForward(can_ai)
  21.     int             can_ai;
  22. {
  23.     LINE           *l;
  24.     LPtr           *next;
  25.     char           *s;        /* string to be moved to new line, if any */
  26.     int             newindex = 0;    /* index of the cursor on the new
  27.                      * line */
  28.  
  29.     /*
  30.      * If we're in insert mode, we need to move the remainder of the current
  31.      * line onto the new line. Otherwise the new line is left blank. 
  32.      */
  33.     if (State == INSERT)
  34.     s = &Curschar->linep->s[Curschar->index];
  35.     else
  36.     s = "";
  37.  
  38.     if ((next = nextline(Curschar)) == NULL)    /* open on last line */
  39.     next = Fileend;
  40.  
  41.     /*
  42.      * By asking for as much space as the prior line had we make sure that
  43.      * we'll have enough space for any auto-indenting. 
  44.      */
  45.     l = newline(strlen(Curschar->linep->s) + SLOP);
  46.     if (l == NULL) {
  47.     emsg("out of memory");
  48.     beep();
  49.     sleep(2);
  50.     return (FALSE);
  51.     }
  52.     if (can_ai && P(P_AI)) {
  53.     char           *p;
  54.  
  55.     /*
  56.      * Copy prior line, and truncate after white space 
  57.      */
  58.     strcpy(l->s, Curschar->linep->s);
  59.  
  60.     for (p = l->s; *p == ' ' || *p == TAB; p++);
  61.     *p = NUL;
  62.     newindex = p - l->s;
  63.     AppendToInsbuff(l->s);
  64.     if (*s != NUL)
  65.         strcat(l->s, s);
  66.  
  67.     /*
  68.      * If we just did an auto-indent, then we didn't type anything on the
  69.      * prior line, and it should be truncated. 
  70.      */
  71.     if (did_ai)
  72.         Curschar->linep->s[0] = NUL;
  73.  
  74.     did_ai = TRUE;
  75.     } else if (*s != NUL) {
  76.     strcpy(l->s, s);    /* copy string to new line */
  77.     }
  78.     if (State == INSERT)    /* truncate current line at cursor */
  79.     *s = NUL;
  80.  
  81.     Curschar->linep->next = l;    /* link neighbors to new line */
  82.     next->linep->prev = l;
  83.  
  84.     l->prev = Curschar->linep;    /* link new line to neighbors */
  85.     l->next = next->linep;
  86.  
  87.     if (next == Fileend) {    /* new line at end */
  88.     l->num = Curschar->linep->num + LINEINC;
  89.     } else if ((l->prev->num) + 1 == l->next->num) {    /* no gap, renumber */
  90.     renum();
  91.     } else {            /* stick it in the middle */
  92.     long            lnum;
  93.  
  94.     lnum = (l->prev->num + l->next->num) / 2;
  95.     l->num = lnum;
  96.     }
  97.  
  98.     *Curschar = *nextline(Curschar);    /* cursor moves down */
  99.     Curschar->index = newindex;
  100.  
  101.     S_NOT_VALID;
  102.     CHANGED;
  103.  
  104.     return (TRUE);
  105. }
  106.  
  107. /*
  108.  * OpenBackward 
  109.  *
  110.  * Add a blank line above the current line. 
  111.  */
  112.  
  113. bool_t
  114. OpenBackward(can_ai)
  115.     int             can_ai;
  116. {
  117.     LINE           *l;
  118.     LINE           *prev;
  119.     int             newindex = 0;    /* index of the cursor on the new
  120.                      * line */
  121.  
  122.     prev = Curschar->linep->prev;
  123.  
  124.     l = newline(strlen(Curschar->linep->s) + SLOP);
  125.     if (l == NULL) {
  126.     emsg("out of memory");
  127.     beep();
  128.     sleep(2);
  129.     return (FALSE);
  130.     }
  131.     Curschar->linep->prev = l;    /* link neighbors to new line */
  132.     prev->next = l;
  133.  
  134.     l->next = Curschar->linep;    /* link new line to neighbors */
  135.     l->prev = prev;
  136.  
  137.     if (can_ai && P(P_AI)) {
  138.     char           *p;
  139.  
  140.     /*
  141.      * Copy current line, and truncate after white space 
  142.      */
  143.     strcpy(l->s, Curschar->linep->s);
  144.  
  145.     for (p = l->s; *p == ' ' || *p == TAB; p++);
  146.     *p = NUL;
  147.     newindex = p - l->s;
  148.     AppendToInsbuff(l->s);
  149.  
  150.     did_ai = TRUE;
  151.     }
  152.     Curschar->linep = Curschar->linep->prev;
  153.     Curschar->index = newindex;
  154.  
  155.     if (prev == Filetop->linep) {    /* new start of file */
  156.     Filemem->linep = l;
  157.     renum();
  158.     } else if ((l->prev->num) + 1 == l->next->num) {    /* no gap, renumber */
  159.     renum();
  160.     } else {            /* stick it in the middle */
  161.     long            lnum;
  162.  
  163.     lnum = (l->prev->num + l->next->num) / 2;
  164.     l->num = lnum;
  165.     }
  166.  
  167.     S_NOT_VALID;
  168.     CHANGED;
  169.  
  170.     return (TRUE);
  171. }
  172.  
  173. int
  174. cntllines(pbegin, pend)
  175.     LPtr           *pbegin, *pend;
  176. {
  177.     register LINE  *lp;
  178.     register int    lnum = 1;
  179.  
  180.     for (lp = pbegin->linep; lp != pend->linep; lp = lp->next)
  181.     lnum++;
  182.  
  183.     return (lnum);
  184. }
  185.  
  186. /*
  187.  * plines(s) - return the number of physical screen lines taken by the
  188.  *             line pointed to by 's'
  189.  */
  190.  
  191. int
  192. plines(s)
  193.     register char  *s;
  194. {
  195.     register int    col = 0;
  196.  
  197.     if (*s == NUL)        /* empty line */
  198.     return 1;
  199.  
  200.     for (; *s != NUL; s++) {
  201.     if (*s == TAB && !P(P_LS))
  202.         col += P(P_TS) - (col % P(P_TS));
  203.     else
  204.         col += chars[*s].ch_size;
  205.     }
  206.  
  207.     /*
  208.      * If list mode is on, then the '$' at the end of the line takes up one
  209.      * extra column. 
  210.      */
  211.     if (P(P_LS))
  212.     col += 1;
  213.  
  214.     /*
  215.      * If 'number' mode is on, add another 8. 
  216.      */
  217.     if (P(P_NU))
  218.     col += 8;
  219.  
  220.     return ((col + (Columns - 1)) / Columns);
  221. }
  222.  
  223. void
  224. fileinfo()
  225. {
  226.     long            l1, l2;
  227.     char            buf[MAX_COLUMNS + 1];
  228.  
  229.     if (bufempty()) {
  230.     msg("Buffer Empty");
  231.     return;
  232.     }
  233.     l1 = cntllines(Filemem, Curschar);
  234.     l2 = cntllines(Filemem, Fileend) - 1;
  235.     sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
  236.         (Filename != NULL) ? Filename : "No File",
  237.         Changed ? " [Modified]" : "",
  238.         l1, l2, (l1 * 100) / l2);
  239.     msg(buf);
  240. }
  241.  
  242. /*
  243.  * gotoline(n) - return a pointer to line 'n' 
  244.  *
  245.  * Returns a pointer to the last line of the file if n is zero, or beyond the
  246.  * end of the file. 
  247.  */
  248. LPtr           *
  249. gotoline(n)
  250.     int             n;
  251. {
  252.     static LPtr     l;
  253.  
  254.     l.index = 0;
  255.  
  256.     if (n == 0)
  257.     l = *prevline(Fileend);
  258.     else {
  259.     LPtr           *p;
  260.  
  261.     for (l = *Filemem; --n > 0; l = *p)
  262.         if ((p = nextline(&l)) == NULL)
  263.         break;
  264.     }
  265.     return &l;
  266. }
  267.  
  268. void
  269. inschar(c)
  270.     char            c;
  271. {
  272.     register char  *p;
  273.     register char  *pend;
  274.  
  275.     /* make room for the new char. */
  276.     if (!canincrease(1))
  277.     return;
  278.  
  279.     p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
  280.     pend = &Curschar->linep->s[Curschar->index];
  281.  
  282.     for (; p > pend; p--)
  283.     *p = *(p - 1);
  284.  
  285.     *p = c;
  286.  
  287.     if (RedrawingDisabled) {
  288.     Curschar->index++;
  289.     return;
  290.     }
  291.     /*
  292.      * If we're in insert mode and showmatch mode is set, then check for
  293.      * right parens and braces. If there isn't a match, then beep. If there
  294.      * is a match AND it's on the screen, then flash to it briefly. If it
  295.      * isn't on the screen, don't do anything. 
  296.      */
  297.     if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
  298.     LPtr           *lpos, csave;
  299.  
  300.     if ((lpos = showmatch()) == NULL)    /* no match, so beep */
  301.         beep();
  302.     else if (LINEOF(lpos) >= LINEOF(Topchar)) {
  303.         /* show the new char first */
  304.         s_refresh(VALID_TO_CURSCHAR);
  305.         csave = *Curschar;
  306.         *Curschar = *lpos;    /* move to matching char */
  307.         cursupdate(UPDATE_CURSOR);
  308.         windgoto(Cursrow, Curscol);
  309.         delay();        /* brief pause */
  310.         *Curschar = csave;    /* restore cursor position */
  311.         cursupdate(UPDATE_ALL);
  312.     }
  313.     }
  314.     inc(Curschar);
  315.  
  316.     CHANGED;
  317. }
  318.  
  319. void
  320. insstr(s)
  321.     register char  *s;
  322. {
  323.     register char  *p;
  324.     register char  *pend;
  325.     register int    n = strlen(s);
  326.  
  327.     /* Move everything in the file over to make */
  328.     /* room for the new string. */
  329.     if (!canincrease(n))
  330.     return;
  331.  
  332.     p = &Curschar->linep->s[strlen(Curschar->linep->s) + n];
  333.     pend = &Curschar->linep->s[Curschar->index];
  334.  
  335.     for (; p > pend; p--)
  336.     *p = *(p - n);
  337.  
  338.     for (; n > 0; n--) {
  339.     *p++ = *s++;
  340.     Curschar->index++;
  341.     }
  342.     CHANGED;
  343. }
  344.  
  345. bool_t
  346. delchar(fixpos, undo)
  347.     bool_t          fixpos;    /* if TRUE fix the cursor position when done */
  348.     bool_t          undo;    /* if TRUE put char deleted into Undo buffer */
  349. {
  350.     int             i;
  351.  
  352.     /* Check for degenerate case; there's nothing in the file. */
  353.     if (bufempty())
  354.     return FALSE;
  355.  
  356.     if (lineempty(Curschar))    /* can't do anything */
  357.     return FALSE;
  358.  
  359.     if (undo)
  360.     AppendToUndobuff(mkstr(gchar(Curschar)));
  361.  
  362.     /* Delete the char. at Curschar by shifting everything in the line down. */
  363.     for (i = Curschar->index + 1; i < Curschar->linep->size; i++)
  364.     Curschar->linep->s[i - 1] = Curschar->linep->s[i];
  365.  
  366.     /*
  367.      * If we just took off the last character of a non-blank line, we don't
  368.      * want to end up positioned at the newline. 
  369.      */
  370.     if (fixpos) {
  371.     if (gchar(Curschar) == NUL && Curschar->index > 0 && State != INSERT)
  372.         Curschar->index--;
  373.     }
  374.     CHANGED;
  375.     return TRUE;
  376. }
  377.  
  378. void
  379. delline(nlines)
  380.     int             nlines;
  381. {
  382.     register LINE  *p;
  383.     register LINE  *q;
  384.  
  385.     while (nlines-- > 0) {
  386.  
  387.     if (bufempty())        /* nothing to delete */
  388.         break;
  389.  
  390.     if (buf1line()) {    /* just clear the line */
  391.         Curschar->linep->s[0] = NUL;
  392.         Curschar->index = 0;
  393.         break;
  394.     }
  395.     p = Curschar->linep->prev;
  396.     q = Curschar->linep->next;
  397.  
  398.     if (p == Filetop->linep) {    /* first line of file so... */
  399.         Filemem->linep = q;    /* adjust start of file */
  400.         Topchar->linep = q;    /* and screen */
  401.     }
  402.     p->next = q;
  403.     q->prev = p;
  404.  
  405.     clrmark(Curschar->linep);    /* clear marks for the line */
  406.  
  407.     /*
  408.      * If deleting the top line on the screen, adjust Topchar 
  409.      */
  410.     if (Topchar->linep == Curschar->linep)
  411.         Topchar->linep = q;
  412.  
  413.     free(Curschar->linep->s);
  414.     free((char *) (Curschar->linep));
  415.  
  416.     Curschar->linep = q;
  417.     Curschar->index = 0;    /* is this right? */
  418.  
  419.     S_NOT_VALID;
  420.     CHANGED;
  421.  
  422.     /* If we delete the last line in the file, back up */
  423.     if (Curschar->linep == Fileend->linep) {
  424.         Curschar->linep = Curschar->linep->prev;
  425.         /* and don't try to delete any more lines */
  426.         break;
  427.     }
  428.     }
  429. }
  430.